﻿//  Copyright (c) 2011 Ray Liang (http://www.dotnetage.com)
//  Dual licensed under the MIT and GPL licenses:
//  http://www.opensource.org/licenses/mit-license.php
//  http://www.gnu.org/licenses/gpl.html

using System.Collections.Generic;
using DNA.OpenAPI.Atom;
using DNA.OpenAPI.OpenSearch;
using DNA.OpenAPI.Rss;
using DNA.Mvc.Publishing;
using System.Linq;
using System;

namespace DNA.Mvc.Publishing
{
    public class ArticleSearchProvider : OpenSearchProvider
    {
        public override string Name
        {
            get
            {
                return "articles";
            }
            set
            {
                base.Name = value;
            }
        }
        public override string Title
        {
            get { return "Articles"; }
        }

        public override bool SupportSuggestion
        {
            get
            {
                return true;
            }
        }

        private IPubContext _pubContext;

        public ArticleSearchProvider(IPubContext pubContext)
        {
            _pubContext = pubContext;
        }

        public override IEnumerable<OpenSearchSuggestion> Suggest(string searchTerms, int count)
        {
            var articles = _pubContext.Articles.Filter(a => a.Title.StartsWith(searchTerms)).OrderBy(a => a.Title).Take(count);
            var comparer = new OpenSearchSuggestionComparer();
            return (from a in articles
                    select new OpenSearchSuggestion()
                    {
                        SearchTerms = a.Title,
                        Description = a.Summary
                    })
                   .ToList()
                   .OrderBy(o => o.SearchTerms)
                   .Distinct(comparer)
                   .Take(count);
        }

        public override IEnumerable<AtomEntry> GetAtomResult(string searchTerms, int pageIndex, int pageSize, out int totalRecords)
        {
            var articles = _FindArticles(searchTerms, pageIndex, pageSize, out totalRecords);

            var entries = new List<AtomEntry>();
            foreach (var art in articles)
            {
                var article = new ArticleWrapper(art);
                //var permalink = ResolveUrl(article);
                var builder = new AtomEntryBuilder(article.Title, article.PermaLink);
                builder.SetSummary(article.Summary);
                builder.SetPublished(article.Posted);
                builder.SetContent(article.Body, src: article.PermaLink);
                builder.SetAuthor(article.UserName, email: System.Web.Security.Membership.GetUser(article.UserName).Email);
                builder.SetLastUpdated(article.LastModified);
                if (!string.IsNullOrEmpty(article.ImageUrl))
                    builder.AddLink(article.ImageUrl, type: "image/png");
                builder.AddLink(article.PermaLink);
                var cats = _GetCategories(article);

                if (cats.Count() > 0)
                    builder.AddCategories((from c in cats
                                           select new AtomCategory()
                                               {
                                                   Text = c.Title,
                                                   Term = c.Title,
                                                   Scheme = c.PermaLink
                                               }).ToList());
                entries.Add(builder.Entry);
            }
            return entries;
        }

        private IEnumerable<CategoryWrapper> _GetCategories(Article article)
        {
            var wrapper = new ArticleWrapper(article);
            return wrapper.AllCategories();
        }

        private IEnumerable<Article> _FindArticles(string searchTerms, int pageIndex, int pageSize, out int totalRecords)
        {
            var skips = (pageIndex - 1) * pageSize;
            var all = _pubContext.Articles.Filter(a => a.Title.Contains(searchTerms) && a.IsPublished && !a.IsPrivate).OrderBy(a => a.Title);
            IEnumerable<Article> articles = null;

            if (skips == 0)
                articles = all.Take(pageSize);
            else
                articles = all.Skip(skips).Take(pageSize);
            totalRecords = _pubContext.Articles.Count(a => a.Title.Contains(searchTerms) && a.IsPublished && !a.IsPrivate);
            return articles;
        }

        public override IEnumerable<RssItem> GetRssResult(string searchTerms, int pageIndex, int pageSize, out int totalRecords)
        {
            //var options = new Models.SearchOption() { SearchText = searchTerms, PageIndex = pageIndex, PageSize = pageSize };
            var articles = _FindArticles(searchTerms, pageIndex, pageSize, out totalRecords);

            var items = new List<RssItem>();
            //totalRecords = options.TotalRecords.Value;

            foreach (var art in articles)
            {
                var article = new ArticleWrapper(art);
                var builder = new RssItemBuilder(article.Title, article.Summary, article.PermaLink);
                builder.SetGuid(article.PermaLink);
                builder.SetPublished(article.Posted);
                builder.SetAuthor(article.UserName);
                builder.SetPublished(article.Posted);
                var cats = _GetCategories(article);
                if (cats.Count() > 0)
                    builder.AddCategories(cats.Select(c => c.Title).ToArray());
                items.Add(builder.Item);
            }
            return items;
        }
    }
}